package com.yourenbang.lingyun.transaction.web.service.impl.petal;

import cn.hutool.core.text.csv.CsvParser;
import cn.hutool.core.text.csv.CsvReadConfig;
import cn.hutool.core.text.csv.CsvRow;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayDataDataserviceBillDownloadurlQueryModel;
import com.alipay.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest;
import com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse;
import com.yourenbang.lingyun.constants.BizCodeMessages;
import com.yourenbang.lingyun.constants.enums.pay.PayFromEnum;
import com.yourenbang.lingyun.constants.enums.pay.PayTypeEnum;
import com.yourenbang.lingyun.core.message.Result;
import com.yourenbang.lingyun.core.util.KLog;
import com.yourenbang.lingyun.core.util.format.CharsetKit;
import com.yourenbang.lingyun.transaction.web.domain.vo.ALiBillListVO;
import com.yourenbang.lingyun.transaction.web.domain.vo.AliBillVO;
import com.yourenbang.lingyun.transaction.web.domain.vo.AliTradeVO;
import com.yourenbang.lingyun.transaction.web.service.pay.PayTypeService;
import com.yourenbang.lingyun.transaction.web.service.petal.BillService;
import com.yourenbang.transaction.api.service.pay.PayTypeApiService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.zip.ZipInputStream;

@Service
@Slf4j
public class BillServiceImpl implements BillService {

    private static final String ALI_SUCCESS_CODE = "10000";
    private static final String EXCEL_NAME_DETAIL = "#支付宝账务明细查询";
    private static final String KLKS_EXCEL_NAME_DETAIL = "#支付宝业务明细查询";
    private static final String EXCEL_NAME_TOTAL = "#支付宝账务汇总查询";

    @Autowired
    private PayTypeService payTypeService;
    @Autowired
    private PayTypeApiService payTypeApiService;

    @Override
    public Result<ALiBillListVO> downloadAliBill(String date) {
        Result<ALiBillListVO> result = Result.builder().success();
        AlipayClient alipayClient = payTypeService.getAlipayClient(PayFromEnum.ali_bill_download);
        Map<String, String> typeParam = payTypeApiService.getPayParams(PayTypeEnum.ALIPAY, PayFromEnum.ali_bill_download);

        /**
         * 查询转账对账单下载地址
         * @param bizContent
         * @return
         * @throws AlipayApiException
         */
        AlipayDataDataserviceBillDownloadurlQueryModel model =
                new AlipayDataDataserviceBillDownloadurlQueryModel();
        AlipayDataDataserviceBillDownloadurlQueryRequest request =
                new AlipayDataDataserviceBillDownloadurlQueryRequest();

        model.setBillType("signcustomer");
//        model.setBillType("trade");

        KLog.info("下载的账单日期:{}", date);
        model.setBillDate(date);
        request.setBizModel(model);

        AlipayDataDataserviceBillDownloadurlQueryResponse response = null;
        try {
            if(StringUtils.isBlank(typeParam.get("appCertPath"))) {
                response = alipayClient.execute(request);
            }else {
                response = alipayClient.certificateExecute(request);
            }
            if (!ALI_SUCCESS_CODE.equals(response.getCode())) {
                Result<ALiBillListVO> fail = Result.builder().fail();
                fail.setDesc(response.getSubMsg());
                fail.setData(new ALiBillListVO(Collections.EMPTY_LIST, 0));
                return fail;
            }
            KLog.info("支付宝账单下载地址:{},返回体:{}", response.getBillDownloadUrl(), response.getBody());
            URL url = new URL(response.getBillDownloadUrl());
            List<AliBillVO> billVos = new ArrayList<>();
            InputStream input = url.openStream();
            ZipInputStream zipIn = new ZipInputStream(input, CharsetKit.CHARSET_GBK);
            CsvRow rows = null;
            CsvParser csv = null;
            while (zipIn.getNextEntry() != null) {
                Reader isr = new InputStreamReader(zipIn, CharsetKit.CHARSET_GBK);
                csv = new CsvParser(isr, new CsvReadConfig());
                rows = csv.nextRow();
                if (EXCEL_NAME_DETAIL.equals(rows.get(0))) {
                    parseBillExcel(billVos, rows, csv);
                }
                KLog.info(rows.get(0));
            }


            ALiBillListVO aLiBillListVO = new ALiBillListVO();
            aLiBillListVO.setList(billVos);
            aLiBillListVO.setSize(billVos.size());
            result.setData(aLiBillListVO);
            KLog.info("返回list大小:{}", billVos.size());
        } catch (Exception e) {
            return Result.builder().fail(BizCodeMessages.TRANSACTION_DOWNLOAD_ALIBILL_ERROR);
        }

        return result;
    }

    @Override
    public Result<JSONObject> downloadKlksAliBill(String date) {
        Result<JSONObject> result = Result.builder().success();
        AlipayClient alipayClient = payTypeService.getAlipayClient(PayFromEnum.ali_bill_download);
        Map<String, String> typeParam = payTypeApiService.getPayParams(PayTypeEnum.ALIPAY, PayFromEnum.ali_bill_download);
        /**
         * 查询交易对账单下载地址
         * @param bizContent
         * @return
         * @throws AlipayApiException
         */
        AlipayDataDataserviceBillDownloadurlQueryModel model =
                new AlipayDataDataserviceBillDownloadurlQueryModel();
        AlipayDataDataserviceBillDownloadurlQueryRequest request =
                new AlipayDataDataserviceBillDownloadurlQueryRequest();

//        model.setBillType("signcustomer");
        model.setBillType("trade");

        KLog.info("下载的账单日期:{}", date);
        model.setBillDate(date);
        request.setBizModel(model);

        AlipayDataDataserviceBillDownloadurlQueryResponse response = null;
        try {
            if(StringUtils.isBlank(typeParam.get("appCertPath"))) {
                response = alipayClient.execute(request);
            }else {
                response = alipayClient.certificateExecute(request);
            }
            if (!ALI_SUCCESS_CODE.equals(response.getCode())) {
                Result fail = Result.builder().fail();
                fail.setDesc(response.getSubMsg());
                fail.setData(Collections.EMPTY_LIST);
                return fail;
            }
            KLog.info("支付宝账单下载地址:{},返回体:{}", response.getBillDownloadUrl(), response.getBody());
            URL url = new URL(response.getBillDownloadUrl());
            List<AliTradeVO> aliTradeVOS = new ArrayList<>();
            InputStream input = url.openStream();
            ZipInputStream zipIn = new ZipInputStream(input, CharsetKit.CHARSET_GBK);
            CsvRow rows = null;
            CsvParser csv = null;
            while (zipIn.getNextEntry() != null) {
                Reader isr = new InputStreamReader(zipIn, CharsetKit.CHARSET_GBK);
                csv = new CsvParser(isr, new CsvReadConfig());
                rows = csv.nextRow();
                if (KLKS_EXCEL_NAME_DETAIL.equals(rows.get(0))) {
                    parseKlksBillExcel(aliTradeVOS, rows, csv);
                }
                KLog.info(rows.get(0));
            }
            JSONObject j = new JSONObject();
            j.put("list", aliTradeVOS);
            result.setData(j);
            KLog.info("返回list大小:{}", aliTradeVOS.size());
        } catch (Exception e) {
            return Result.builder().fail(BizCodeMessages.TRANSACTION_DOWNLOAD_ALIBILL_ERROR);
        }

        return result;
    }


    private void parseBillExcel(List<AliBillVO> billVos, CsvRow rows, CsvParser csv) {
        int r = 1;
        while (rows != null) {
            KLog.info("当前读取第{}行", r++);
            Iterator<String> colsIterator = rows.iterator();

            AliBillVO vo = new AliBillVO();
            int col = 1;
            a:
            while (colsIterator.hasNext()) {
                String next = colsIterator.next().trim();
                KLog.info(next);
                switch (col) {
                    case 1:
                        char c = next.charAt(0);
                        if (c == '#' || c == '账') {
                            vo = null;
                            break a;
                        }
                        vo.setBillId(next);
                        break;
                    case 2:
                        vo.setBusinessId(next);
                        break;
                    case 3:
                        vo.setMerchantOrderNo(next);
                        break;
                    case 4:
                        vo.setProduct(next);
                        break;
                    case 5:
                        vo.setTradeTime(next);
                        break;
                    case 6:
                        vo.setAccount(next);
                        break;
                    case 7:
                        if (StringUtils.isNotEmpty(next)) {
                            vo.setInAmount(new BigDecimal(next));
                        }
                        break;
                    case 8:
                        if (StringUtils.isNotEmpty(next)) {
                            vo.setPayAmount(new BigDecimal(next));
                        }
                        break;
                    case 9:
                        if (StringUtils.isNotEmpty(next)) {
                            vo.setLeftAmount(new BigDecimal(next));
                        }
                        break;
                    case 10:
                        vo.setTradeChannel(next);
                        break;
                    case 11:
                        vo.setBusinessType(next);
                        break;
                    case 12:
                        vo.setRemark(next);
                        break;
                    default:
                        break;
                }

                KLog.info("csv读取的第{}列:{}", col++, next);
            }
            KLog.info("加入的实体:{}", vo);
            if (vo != null) {
                billVos.add(vo);
            }

            rows = csv.nextRow();
        }
    }

    private void parseKlksBillExcel(List<AliTradeVO> aliTradeVOS, CsvRow rows, CsvParser csv) {
        int r = 1;
        while (rows != null) {
            KLog.info("当前读取第{}行", r++);
            Iterator<String> colsIterator = rows.iterator();

            AliTradeVO vo = new AliTradeVO();

            int col = 1;
            a:
            while (colsIterator.hasNext()) {
                String next = colsIterator.next();
                next = next.trim();
                KLog.info(next);
                switch (col) {
                    case 1:
                        char c = next.charAt(0);
                        if (c == '#' || c == '支') {
                            vo = null;
                            break a;
                        }
                        vo.setAliTradeNo(next);
                        break;
                    case 2:
                        vo.setMerchantOrderNo(next);
                        break;
                    case 3:
                        vo.setBusinessType(next);
                        break;
                    case 4:
                        vo.setProduct(next);
                        break;
                    case 5:
                        vo.setCreateTime(next);
                        break;
                    case 6:
                        vo.setFinishTime(next);
                        break;
                    case 11:
                        vo.setThirdAccount(next);
                        break;
                    case 12:
                        if (StringUtils.isNotEmpty(next)) {
                            vo.setOrderAmt(new BigDecimal(next));
                        }
                        break;
                    case 13:
                        if (StringUtils.isNotEmpty(next)) {
                            vo.setMerchantInAmt(new BigDecimal(next));
                        }
                        break;
                    case 22:
                        if (StringUtils.isNotBlank(next)) {
                            vo.setRefundId(next);
                        }
                        break;
                    case 23:
                        vo.setFee(new BigDecimal(next));
                        break;
                    case 25:
                        vo.setRemark(next);
                        break;
                    default:
                        break;
                }

                KLog.info("csv读取的第{}列:{}", col++, next);
            }
            KLog.info("加入的实体:{}", vo);
            if (vo != null) {
                aliTradeVOS.add(vo);
            }

            rows = csv.nextRow();
        }

    }

//    public static void main(String[] args) {
//        Result<JSONObject> result = Result.builder().success();
//        AlipayClient alipayClient = aliConfig.getAlipayClient("kuaishouzixun_tx");
//        /**
//         * 查询交易对账单下载地址
//         * @param bizContent
//         * @return
//         * @throws AlipayApiException
//         */
//        AlipayDataDataserviceBillDownloadurlQueryModel model =
//                new AlipayDataDataserviceBillDownloadurlQueryModel();
//        AlipayDataDataserviceBillDownloadurlQueryRequest request =
//                new AlipayDataDataserviceBillDownloadurlQueryRequest();
//
//        model.setBillType("signcustomer");
////        model.setBillType("trade");
//
//
//        model.setBillDate("2020-08-03");
//        request.setBizModel(model);
//
//        AlipayDataDataserviceBillDownloadurlQueryResponse response = null;
//        try {
//            Company company = Company.getCompany("kuaishouzixun_tx");
//            if (company == null || StringUtils.isBlank(company.getAppCertPath())) {
//                response = alipayClient.execute(request);
//            } else {
//                response = alipayClient.certificateExecute(request);
//            }
//            if (!ALI_SUCCESS_CODE.equals(response.getCode())) {
//                Result fail = Result.builder().fail();
//                fail.setDesc(response.getSubMsg());
//                fail.setData(Collections.EMPTY_LIST);
//            }
//            KLog.info("支付宝账单下载地址:{},返回体:{}", response.getBillDownloadUrl(), response.getBody());
//
//        } catch (AlipayApiException e) {
//            e.printStackTrace();
//        }
//    }
}
